/**
 * 
 * DIRECTV PROPRIETARY
 * Copyright© 2014 DIRECTV, INC.
 * UNPUBLISHED WORK
 * ALL RIGHTS RESERVED
 * 
 * This software is the confidential and proprietary information of
 * DIRECTV, Inc. ("Proprietary Information").  Any use, reproduction, 
 * distribution or disclosure of the software or Proprietary Information, 
 * in whole or in part, must comply with the terms of the license 
 * agreement, nondisclosure agreement or contract entered into with 
 * DIRECTV providing access to this software.
 */
package com.direct.ratelimit.limit;

import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.concurrent.ConcurrentHashMap;

import com.direct.ratelimit.RateLimitRequest;
import com.direct.ratelimit.utils.BeanUtils;

/**
 * in memory dao provides a simple cache storing limits and overrides.
 * 
 * @author srstone
 * 
 */
public class InMemoryLimitDAO implements LimitDAO {

	// private ConcurrentHashMap<String, Collection<Limit>> limitStore = new ConcurrentHashMap<String, Collection<Limit>>();
	private Collection<Limit> limitStore = Collections.synchronizedCollection(new HashSet<Limit>());

	private ConcurrentHashMap<String, Collection<ClientLimitOverride>> clientOverrideStore = new ConcurrentHashMap<String, Collection<ClientLimitOverride>>();

	@Override
	public Collection<Limit> getLimits(RateLimitRequest rateLimitRequest) {

		Collection<Limit> response = new LinkedList<Limit>();

		for (Limit limit : limitStore) {

			// this is attempting to validate that this limit has the same resource identifier value even if they are both null
			if (rateLimitRequest.getResourceIdentifer() == limit.getResourceIdentifier() || (rateLimitRequest.getResourceIdentifer() != null
					&& rateLimitRequest.getResourceIdentifer().equals(limit.getResourceIdentifier()))) {

				response.add(BeanUtils.clone(limit));
			}
		}

		return response;
	}

	class Key {
		public final String limitid;
		public final String clientId;
		public final String apiid;

		public Key(String limitid, String clientId, String apiid) {
			super();
			this.limitid = limitid;
			this.clientId = clientId;
			this.apiid = apiid;
		}

	}

	@Override
	public void addLimit(Limit limit) {
		// TODO Auto-generated method stub
		// KISS just inddex on limit id all other searches mean a full "table" scan
		// we clone this so that modifications dont update the cache

		// Collection<Limit> limits = limitStore.get(limit.getId());
		// if (limits == null) {
		// limits = new LinkedList<Limit>();
		// limitStore.put(limit.getId(), limits);
		// }

		limitStore.add(BeanUtils.clone(limit));

	}

	@Override
	public Collection<ClientLimitOverride> getClientLimitOverrides(Collection<Limit> limits, String clientId) {
		// TODO Auto-generated method stub
		Collection<ClientLimitOverride> response = new LinkedList<ClientLimitOverride>();

		Collection<ClientLimitOverride> overrides = clientOverrideStore.get(clientId);

		for (ClientLimitOverride clientLimitOverride : overrides) {
			// check if this is one of the limits they sent in
			for (Limit limit : limits) {
				if (clientLimitOverride.getLimitId().equals(limit.getId())) {
					response.add(clientLimitOverride);
					break;
				}
			}
		}

		return response;
	}

	@Override
	public void addClientOverride(ClientLimitOverride clientLimitOverride) {
		// TODO Auto-generated method stub
		Collection<ClientLimitOverride> clientLimitOverrides = clientOverrideStore.get(clientLimitOverride.getClientId());
		if (clientLimitOverrides == null) {
			clientLimitOverrides = new LinkedList<ClientLimitOverride>();
			clientOverrideStore.put(clientLimitOverride.getClientId(), clientLimitOverrides);
		}
		clientLimitOverrides.add(clientLimitOverride);

	}

}
